﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GeoSwarm_Editor
{
    public partial class LevelData : Form
    {

        private int[] towerData = new int[6];
        /*
         * Access using this format: creepData[creep ID, data ID]
         * Data IDs:
         *  0 Creep Speed
         *  1 Creep Health
         * For a list of creep IDs, see Wave.cs
         */
        private int[,] creepData = new int[7,2];

        private List<Hexagonal.Hex> spawnHexes = new List<Hexagonal.Hex>();

        public LevelData()
        {
            InitializeComponent();

            // Set up default values using default values set in control properties
            for (int i = 0; i < towerData.Length; i++)
            {
                towerData[i] = (int)control_TowerCost.Value;
            }

            for (int i = 0; i < creepData.GetLength(0); i++)
            {
                for (int j = 0; j < creepData.GetLength(1); j++)
                {
                    if (j == 0)
                        // Default creed speed
                        creepData[i, j] = (int)control_CreepSpeed.Value;
                    else
                        // Default creep health
                        creepData[i, j] = (int)control_CreepHealth.Value;
                }
            }
        }

        /*
         * Adds a wave using entered information
         */
        private void AddWave()
        {
            // Add the default wave
            if (spawnHexes.Count > 0)
            {
                control_Waves.Items.Add(new Wave(spawnHexes[0]));
                new EditWave((Wave)control_Waves.Items[control_Waves.Items.Count - 1], spawnHexes, control_Waves, this);
                this.Enabled = false;
            }
            else
                MessageBox.Show("A wave could not be added - there are no spawn hexes.", "Oops!");
        }

        private void control_dataOK_Click(object sender, EventArgs e)
        {
            this.Hide();
        }

        #region Main Creeps and Towers Selection Handlers

        private void control_Creeps_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (control_Creeps.SelectedIndex >= 0)
            {
                Image[] creepImages = {
                    global::GeoSwarm_Editor.Properties.Resources.c_0,
                    global::GeoSwarm_Editor.Properties.Resources.c_1,
                    global::GeoSwarm_Editor.Properties.Resources.c_2,
                    global::GeoSwarm_Editor.Properties.Resources.c_3,
                    global::GeoSwarm_Editor.Properties.Resources.c_4,
                    global::GeoSwarm_Editor.Properties.Resources.c_5,
                    global::GeoSwarm_Editor.Properties.Resources.c_7
                };
                groupBox6.Enabled = true;
                control_CreepSpeed.Value = creepData[control_Creeps.SelectedIndex, 0];
                control_CreepHealth.Value = creepData[control_Creeps.SelectedIndex, 1];
                creepPic.BackgroundImage = creepImages[control_Creeps.SelectedIndex];
            }
            else groupBox6.Enabled = false;
        }

        private void control_Towers_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (control_Towers.SelectedIndex >= 0)
            {
                Image[] towerImages = {
                    global::GeoSwarm_Editor.Properties.Resources.t_0,
                    global::GeoSwarm_Editor.Properties.Resources.t_1,
                    global::GeoSwarm_Editor.Properties.Resources.t_2,
                    global::GeoSwarm_Editor.Properties.Resources.t_3,
                    global::GeoSwarm_Editor.Properties.Resources.t_4,
                    global::GeoSwarm_Editor.Properties.Resources.t_5
                };
                groupBox5.Enabled = true;
                control_TowerCost.Value = towerData[control_Towers.SelectedIndex];
                towerPic.BackgroundImage = towerImages[control_Towers.SelectedIndex];
            }
            else groupBox6.Enabled = false;
        }

        #endregion

        #region Properties

        public int[] TowerData
        {
            get
            {
                return towerData;
            }
            set
            {
                int i = 0;
                foreach(int data in value)
                {
                    if (data == 0)
                        value[i] = 10;
                    i++;
                }
                towerData = value;
            }
        }

        public int[,] CreepData
        {
            get
            {
                return creepData;
            }
            set
            {
                for (int i = 0; i < value.GetLength(0); i++)
                {
                    if (value[i, 0] == 0)
                        value[i, 0] = 30;
                    if (value[i, 1] == 0)
                        value[i, 1] = 15;
                }
                creepData = value;
            }
        }

        public List<Hexagonal.Hex> SpawnHexes
        {
            get
            {
                return spawnHexes;
            }
        }

        public string LevelName
        {
            get
            {
                return control_LevelName.Text;
            }
            set
            {
                control_LevelName.Text = value;
            }
        }

        public string LevelDesc
        {
            get
            {
                return control_LevelDescription.Text;
            }
            set
            {
                control_LevelDescription.Text = value;
            }
        }

        public string LevelHint1
        {
            get
            {
                return control_LevelHint1.Text;
            }
            set
            {
                control_LevelHint1.Text = value;
            }
        }

        public string LevelHint2
        {
            get
            {
                return control_LevelHint2.Text;
            }
            set
            {
                control_LevelHint2.Text = value;
            }
        }

        public int StartCash
        {
            get
            {
                return (int)control_StartCash.Value;
            }
            set
            {
                control_StartCash.Value = value;
            }
        }

        public int StartLives
        {
            get
            {
                return (int)control_StartLives.Value;
            }
            set
            {
                control_StartLives.Value = value;
            }
        }

        public bool EndlessWaves
        {
            get
            {
                return control_Endless.Checked;
            }
            set
            {
                control_Endless.Checked = value;
            }
        }

        public int[] EnabledCreeps
        {
            get
            {
                int[] enabledCreeps = new int[control_Creeps.CheckedItems.Count];
                int i = 0;
                foreach (int creepID in control_Creeps.CheckedIndices)
                {
                    enabledCreeps[i] = creepID;
                    i++;
                }
                return enabledCreeps;
            }
            set
            {
                foreach (int creepID in value)
                {
                    control_Creeps.SetItemChecked(creepID, true);
                }
            }
        }

        public int[] EnabledTowers
        {
            get
            {
                int[] enabledTowers = new int[control_Towers.CheckedItems.Count];
                int i = 0;
                foreach (int towerID in control_Towers.CheckedIndices)
                {
                    enabledTowers[i] = towerID;
                    i++;
                }
                return enabledTowers;
            }
            set
            {
                foreach (int towerID in value)
                {
                    control_Towers.SetItemChecked(towerID, true);
                }
            }
        }

        public Wave[] Waves
        {
            get
            {
                Wave[] waves = new Wave[control_Waves.Items.Count];
                control_Waves.Items.CopyTo(waves, 0);
                return waves;
            }
            set
            {
                control_Waves.Items.Clear();
                control_Waves.Items.AddRange(value);
            }
        }

        public decimal WaveDelay
        {
            get
            {
                return control_WaveDelay.Value;
            }
            set
            {
                control_WaveDelay.Value = value;
            }
        }

        public decimal SpawnDelay
        {
            get
            {
                return control_SpawnDelay.Value;
            }
            set
            {
                control_SpawnDelay.Value = value;
            }
        }

        public decimal SpeedFactor
        {
            get
            {
                return control_SpeedFactor.Value;
            }
            set
            {
                control_SpeedFactor.Value = value;
            }
        }

        public decimal HealthFactor
        {
            get
            {
                return control_HealthFactor.Value;
            }
            set
            {
                control_HealthFactor.Value = value;
            }
        }

        public decimal WealthFactor
        {
            get
            {
                return control_WealthFactor.Value;
            }
            set
            {
                control_WealthFactor.Value = value;
            }
        }

        #endregion

        #region Value Changes

        // Save changes to the arrays as they are made

        /*
         * Creep Settings
         */

        private void control_CreepSpeed_ValueChanged(object sender, EventArgs e)
        {
            creepData[control_Creeps.SelectedIndex, 0] = (int)control_CreepSpeed.Value;
        }

        private void control_CreepHealth_ValueChanged(object sender, EventArgs e)
        {
            creepData[control_Creeps.SelectedIndex, 1] = (int)control_CreepHealth.Value;
        }

        /*
         * Tower Settings
         */

        private void control_TowerCost_ValueChanged(object sender, EventArgs e)
        {
            towerData[control_Towers.SelectedIndex] = (int)control_TowerCost.Value;
        }

        #endregion

        private void control_Waves_SelectedIndexChanged(object sender, EventArgs e)
        {
            ValidateWavesControls();
        }

        private void button_AddNew_Click(object sender, EventArgs e)
        {
            if (spawnHexes.Count > 0)
                AddWave();
            else
                MessageBox.Show("You can't add a wave because there are no spawn hexes on the level.", "Oops!");
        }

        private void button_Remove_Click(object sender, EventArgs e)
        {
            int newSelection = control_Waves.SelectedIndex - 1;
            control_Waves.Items.RemoveAt(control_Waves.SelectedIndex);
            ValidateWavesControls();
            if (newSelection >= 0 && control_Waves.Items.Count > 0)
                control_Waves.SelectedIndex = newSelection;
            else if (control_Waves.Items.Count > 0)
                control_Waves.SelectedIndex = 0;
        }

        private void ValidateWavesControls()
        {
            if (control_Waves.SelectedIndex >= 0)
            {
                // Only allow moving if there is more than one item
                if (control_Waves.Items.Count > 1)
                {
                    // if first item, only enable moving down
                    if (control_Waves.SelectedIndex == 0)
                    {
                        button_MoveDown.Enabled = true;
                        button_MoveUp.Enabled = false;
                    }
                    // if last item, only enable moving up
                    else if (control_Waves.SelectedIndex == (control_Waves.Items.Count - 1))
                    {
                        button_MoveDown.Enabled = false;
                        button_MoveUp.Enabled = true;
                    }
                    // if it's in the middle, enable both
                    else if (control_Waves.SelectedIndex > 0 && control_Waves.SelectedIndex < (control_Waves.Items.Count - 1))
                    {
                        button_MoveDown.Enabled = true;
                        button_MoveUp.Enabled = true;
                    }
                }
                button_Remove.Enabled = true;
                button_EditWave.Enabled = true;
            }
            else
            {
                button_MoveUp.Enabled = false;
                button_MoveDown.Enabled = false;
                button_Remove.Enabled = false;
                button_EditWave.Enabled = false;
            }
        }

        private void button_MoveUp_Click(object sender, EventArgs e)
        {
            int currentIndex = control_Waves.SelectedIndex;
            Object tempSwap = control_Waves.SelectedItem;
            control_Waves.Items.RemoveAt(currentIndex);
            control_Waves.Items.Insert(currentIndex - 1, tempSwap);
            control_Waves.SelectedIndex = currentIndex - 1;
            ValidateWavesControls();
        }

        private void button_MoveDown_Click(object sender, EventArgs e)
        {
            int currentIndex = control_Waves.SelectedIndex;
            Object tempSwap = control_Waves.SelectedItem;
            control_Waves.Items.RemoveAt(currentIndex);
            control_Waves.Items.Insert(currentIndex + 1, tempSwap);
            control_Waves.SelectedIndex = currentIndex + 1;
            ValidateWavesControls();
        }

        private void button_EditWave_Click(object sender, EventArgs e)
        {
            new EditWave((Wave)control_Waves.SelectedItem, spawnHexes, control_Waves, this);
        }
    }
}